package com.usefullc.system.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.usefullc.common.constants.SubPubConstants;
import com.usefullc.system.enums.JobTemplateStatusEnum;
import com.usefullc.common.enums.YesNoEnum;
import com.usefullc.common.exception.BizException;
import com.usefullc.common.user.OnlineUser;
import com.usefullc.common.user.OnlineUserManager;
import com.usefullc.common.util.BeanUtils;
import com.usefullc.system.domain.JobTemplate;
import com.usefullc.system.entity.Pager;
import com.usefullc.system.mapper.JobTemplateMapper;
import com.usefullc.system.query.JobTemplateQuery;
import com.usefullc.system.service.component.scheduler.IQuartzHelper;
import com.usefullc.system.service.component.scheduler.QuartzJobComponent;
import com.usefullc.system.vo.JobTemplateVo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 定时任务模板服务类
 * @author: 星空
 * @date: 2022-09-06
 */
@Service
public class JobTemplateService extends AbstractBizService<JobTemplateMapper, JobTemplate, JobTemplateQuery> implements IQuartzHelper {

    @Autowired
    private QuartzJobComponent quartzJobComponent;

    @Autowired
    private MessagePublishService messagePublishService;

    @Override
    protected QueryWrapper<JobTemplate> getQueryWrapper(JobTemplateQuery query) {
        QueryWrapper<JobTemplate> queryWrapper = super.getQueryWrapper(query);
        OnlineUser loginUser = OnlineUserManager.getLoginUser();
        if(loginUser != null && loginUser.getTenantId() != 0L){
            query.setTenantId(loginUser.getTenantId());
        }
        return queryWrapper;
    }

    public Pager<JobTemplateVo> findVoByPage(JobTemplateQuery query){
        Pager<JobTemplate> page = this.findByPage(query);
        Pager<JobTemplateVo> newPage = new Pager<>(page);
        List<JobTemplate> dataList = page.getDataList();
        List<JobTemplateVo> newDataList = new ArrayList<>();
        newPage.setDataList(newDataList);
        for (JobTemplate JobTemplate : dataList) {
            JobTemplateVo JobTemplateVo = BeanUtils.beanCopy(JobTemplate, JobTemplateVo.class);
            newDataList.add(JobTemplateVo);
        }
        return newPage;
    }


    public void execute(){
        logger.info("job template execute start...");
        JobTemplateQuery jobTemplateQuery = new JobTemplateQuery();
        jobTemplateQuery.setEnabled(YesNoEnum.YES.getCode());
        List<JobTemplate> dataList = this.findAll(jobTemplateQuery);
        if (CollectionUtils.isNotEmpty(dataList)) {
            Map<String, String> dataMap = dataList.stream().collect(Collectors.toMap(data -> data.getId().toString(), data -> data.getCron()));
            quartzJobComponent.start(dataMap);
        }
    }

    @Transactional
    public void saveJob(JobTemplate jobTemplate){
        jobTemplate.setStatus(JobTemplateStatusEnum.READY.getCode());
        jobTemplate.setEnabled(YesNoEnum.NO.getCode());
        this.save(jobTemplate);
//        if(jobTemplate.getEnabled() == YesNoEnum.YES.getCode()){
//        quartzJobComponent.add(jobTemplate.getId().toString(),jobTemplate.getCron());
//        }
    }

    @Transactional
    public void updateJob(JobTemplate jobTemplate){
        this.save(jobTemplate);
//        if(jobTemplate.getEnabled() == YesNoEnum.YES.getCode()){
//            quartzJobComponent.update(jobTemplate.getId().toString(),jobTemplate.getCron());
//        }
    }

    @Transactional
    public void deleteJob(List<Long> ids){
        this.delete(ids);
        for (Long id : ids) {
            quartzJobComponent.remove(id.toString());
        }
    }


    @Transactional
    public void enableJob(List<Long> ids){
        for (Long id : ids) {
            if(isRunning(id.toString())){
                throw new BizException("该作业正在运行中，请等运行结束后再操作",false);
            }
        }
        this.getBaseMapper().updateAllEnabled(ids,YesNoEnum.YES.getCode());
        for (Long id : ids) {
            JobTemplate jobTemplate = this.findById(id);
            quartzJobComponent.add(id.toString(), jobTemplate.getCron());
        }
    }

    @Transactional
    public void disableJob(List<Long> ids){
        this.getBaseMapper().updateAllEnabled(ids,YesNoEnum.NO.getCode());
        for (Long id : ids) {
            quartzJobComponent.remove(id.toString());
        }
    }


    @Transactional
    public void startNow(Long id,String param){
        if(isRunning(id.toString())){
            throw new BizException("该作业正在运行中，请等运行结束后再操作",false);
        }
        this.publish(id,param);
    }


    public void publish(Long id,String param){
        JobTemplate jobTemplate = this.findById(id);
        logger.info("publish jobTemplate={}",jobTemplate);
        String publishKey = SubPubConstants.JOB +"_"+jobTemplate.getCategory()+"_"+jobTemplate.getId();
        if (StringUtils.isEmpty(param)) {
            param = jobTemplate.getParam();
        }
        messagePublishService.publish(publishKey,param,jobTemplate.getTenantId());
//        jobTemplate.setStatus(JobTemplateStatusEnum.RUNNING.getCode());
//        jobTemplateService.update(jobTemplate);
        this.getBaseMapper().updateStatus(id,JobTemplateStatusEnum.RUNNING.getCode());
    }


    @Override
    public boolean isRunning(String key) {
        Long id = Long.valueOf(key);
        JobTemplate jobTemplate = this.findById(id);
        return jobTemplate.getStatus() == JobTemplateStatusEnum.RUNNING.getCode();
    }

    @Override
    public void complete(String key) {
        Long id = Long.valueOf(key);
        this.getBaseMapper().updateStatus(id,JobTemplateStatusEnum.READY.getCode());
    }
}
